package com.hp.bon.sgw.start;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.hp.bon.sgw.domain.MsgTransRecord;
import com.hp.bon.sgw.service.OuterDBDataService;
import com.hp.bon.sgw.util.LogTool;
import com.hp.bon.sgw.util.dcc.DccAvpHelper;

/**
 * 负责将业务数据记录从JSON文件中发布/写入到Oracle库中，需要最少1小时调度一次。
 * 
 * @author wuzhih
 * 
 */
public class AnswerMsgValidator {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = LoggerFactory.getLogger(AnswerMsgValidator.class);
	private volatile boolean stopFlag = false;

	private OuterDBDataService outDataStoreService;
	private String patternPath;
	private String patternFileExt = ".xsd";
	private Map<String, StreamSource> patternMap;
	private final static SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

	public void stop() {
		stopFlag = true;
	}

	public void doJob() {
		logger.info("do validate answer job ...");
		this.loadXmlPatterns();
		List<MsgTransRecord> list = outDataStoreService.getUnvalidateAnswers();
		for (MsgTransRecord r : list) {
			OperationResult or = this.validateXml(DccAvpHelper.getCapability(r.getServiceContextId()), r.getMsgDetail());
			r.setValidateCode(or.getResultCode());
			r.setValidateTime(new Timestamp(System.currentTimeMillis()));
			r.setValidateDesc(or.getMsgKey());
		}
		outDataStoreService.updateMsgTransRecords(list);
		logger.info("do validate answer job end.");
	}

	private void loadXmlPatterns() {
		logger.info("load xml pattern defines from dir:" + patternPath);
		File fileDir = new File(this.patternPath);
		Map<String, StreamSource> map = new HashMap<String, StreamSource>();
		String capability = "";
		String fileName = "";

		for (File file : fileDir.listFiles()) {
			fileName = file.getName();
			if (file.isFile() && fileName.endsWith(this.patternFileExt)) {
				try {
					capability = fileName.substring(0, fileName.lastIndexOf("."));
					StreamSource ss = new StreamSource(file);
					map.put(capability, ss);
				} catch (Exception e) {
					logger.error("load err: " + file + " " + e);
				}
			}
		}
		this.patternMap = map;
		logger.info("load total xml pattern def " + map.size());
	}

	private OperationResult validateXml(String capabilty, String xml) {
		try {
			StreamSource ss = this.patternMap.get(capabilty);
			if (ss == null) {
				return new OperationResult(2, "no pattern");
			}
			InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
			Schema schema = schemaFactory.newSchema(ss);
			Validator val = schema.newValidator();
			val.validate(new StreamSource(inputStream));
		} catch (Exception e) {
			// logger.warn(e.toString());
			return new OperationResult(1, e.getMessage().substring(e.getMessage().indexOf(" ")));
		}
		return new OperationResult(0);
	}

	class OperationResult {
		private int resultCode;
		private String msgKey;

		OperationResult(int _resultCode) {
			resultCode = _resultCode;
		}

		OperationResult(int _resultCode, String _msgKey) {
			resultCode = _resultCode;
			msgKey = _msgKey;
		}

		public int getResultCode() {
			return resultCode;
		}

		public void setResultCode(int resultCode) {
			this.resultCode = resultCode;
		}

		public String getMsgKey() {
			return msgKey;
		}

		public void setMsgKey(String msgKey) {
			this.msgKey = msgKey;
		}

	}

	public void start(String[] args) {
		LogTool.installSLF4JBridge();
		String propFile = null;
		if (args.length > 0) {
			propFile = args[0];
		} else {
			propFile = "etc/validate-answer.properties";
		}
		LogTool.loadProperty(propFile);
		String patternPath = System.getProperty("patternPath");
		String[] springXmls = new String[] { "spring-validate-answer.xml", };
		ClassPathXmlApplicationContext ctx = null;
		try {
			ctx = new ClassPathXmlApplicationContext(springXmls);
			OuterDBDataService outerDataService = ctx.getBean(OuterDBDataService.class);
			AnswerMsgValidator validateAnswer = new AnswerMsgValidator();
			validateAnswer.outDataStoreService = outerDataService;
			validateAnswer.patternPath = patternPath;
			while (!stopFlag) {
				validateAnswer.doJob();
				try {
					Thread.sleep(15 * 60 * 1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		} finally {
			if (ctx != null) {
				ctx.close();
			}
		}
	}

	public static void main(String[] args) {
		new AnswerMsgValidator().start(args);
	}
}
